﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
///  @brief 定义了游戏的主要逻辑模型，包括地图管理、分数计算、游戏结束判断等。
/// </summary>
public class Model : MonoBehaviour {
    /**
     * @brief 正常游戏地图的行数。
     */
    public const int NORMAL_ROWS = 20;

    /**
     * @brief 地图的最大行数。
     */
    public const int MAX_ROWS = 23;

    /**
     * @brief 地图的最大列数。
     */
    public const int MAX_COLUMNS = 10;

    /**
     * @brief 地图的二维数组，用于存储地图上的每个块。
     */
    private Transform[,] map = new Transform[MAX_COLUMNS, MAX_ROWS];

    /**
     * @brief 当前得分。
     */
    private int score = 0;

    /**
     * @brief 最高得分。
     */
    private int highScore = 0;

    /**
     * @brief 当前游戏已玩的局数。
     */
    private int numbersGame = 0;

    /**
     * @brief 获取当前得分。
     * @return 当前得分。
     */
    public int Score { get { return score; } }

    /**
     * @brief 获取最高得分。
     * @return 最高得分。
     */
    public int HighScore { get { return highScore; } }

    /**
     * @brief 获取当前游戏已玩的局数。
     * @return 当前游戏已玩的局数。
     */
    public int NumbersGame { get { return numbersGame; } }

    /**
     * @brief 标记数据是否需要更新。
     */
    public bool isDataUpdate = false;

    /**
     * @brief 在对象加载时调用，用于加载数据。
     */
    private void Awake()
    {
        LoadData();
    }
    /**
     * @brief 检查给定的Transform对象（形状）是否有效放置在地图上。
     * @param t 要检查的Transform对象。
     * @return 如果有效放置则返回true，否则返回false。
     */
    public bool IsValidMapPosition(Transform t)
    {
        foreach(Transform child in t)
        {
            if (child.tag != "Block") continue;
            Vector2 pos = child.position.Round();
            if (IsInsideMap(pos) == false) return false;
            if (map[(int)pos.x, (int)pos.y] != null) return false;
        }
        return true;
    }
    /**
     * @brief 检查游戏是否结束。
     * @return 如果游戏结束则返回true，否则返回false。
     */
    public bool IsGameOver()
    {
        for(int i = NORMAL_ROWS; i < MAX_ROWS; i++)
        {
            for( int j = 0; j < MAX_COLUMNS; j++)
            {
                if (map[j, i] != null)
                {
                    numbersGame++;
                    SaveData();
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * @brief 检查给定的位置是否在地图范围内。
     * @param pos 要检查的位置。
     * @return 如果在地图范围内则返回true，否则返回false。
     */
    private bool IsInsideMap(Vector2 pos)
    {
        return pos.x >= 0 && pos.x < MAX_COLUMNS && pos.y >= 0;
    }
    /**
     * @brief 将形状放置在地图上，并检查是否需要消除行。
     * @param t 要放置的Transform对象。
     * @return 如果需要消除行则返回true，否则返回false。
     */
    public bool PlaceShape(Transform t)
    {
        foreach(Transform child in t)
        {
            Debug.Log(t);
            if (child.tag != "Block") continue;
            Vector2 pos = child.position.Round();
            map[(int)pos.x, (int)pos.y] = child;
        }
        return CheckMap();
    }
    /**
     * @brief 检查地图是否需要消除行。
     * @return 如果需要消除行则返回true，否则返回false。
     */
    private bool CheckMap()
    {
        int count = 0;
        for(int i =0;i< MAX_ROWS;i++)
        {
            bool isFull = CheckIsRowFull(i);
            if (isFull)
            {
                count++;
                DeleteRow(i);
                MoveDownRowsAbove(i + 1);
                i--;
            }
        }
        if (count > 0)
        {
            score += (count * 100);
            if (score > highScore)
            {
                highScore = score;
            }
            isDataUpdate = true;
            return true;
        }
        else return false;
    }
    /**
     * @brief 检查指定的行是否已满。
     * @param row 要检查的行号。
     * @return 如果行已满则返回true，否则返回false。
     */
    private bool CheckIsRowFull(int row)
    {
        for(int i = 0; i < MAX_COLUMNS; i++)
        {
            if (map[i, row] == null) return false;
        }
        return true;
    }
    /**
     * @brief 删除指定的行。
     * @param row 要删除的行号。
     */
    private void DeleteRow(int row)
    {
        for (int i = 0; i < MAX_COLUMNS; i++)
        {
            Destroy(map[i, row].gameObject);
            map[i, row] = null;
        }
    }
    /**
     * @brief 将指定行以上的所有行向下移动一行。
     * @param row 从哪一行开始向下移动。
     */
    private void MoveDownRowsAbove(int row)
    {
        for(int i = row; i < MAX_ROWS; i++)
        {
            MoveDownRow(i);
        }
    }
    /**
     * @brief 将指定的行向下移动一行。
     * @param row 要移动的行号。
     */
    private void MoveDownRow(int row)
    {
        for( int i= 0; i < MAX_COLUMNS; i++)
        {
            if(map[i, row] != null)
            {
                map[i, row - 1] = map[i, row];
                map[i, row] = null;
                map[i, row - 1].position += new Vector3(0, -1, 0);
            }
        }
    }
    /**
     * @brief 从PlayerPrefs加载数据。
     */
    private void LoadData()
    {
        highScore = PlayerPrefs.GetInt("HighScore", 0);
        numbersGame = PlayerPrefs.GetInt("NumbersGame", 0);
    }
    /**
     * @brief 将数据保存到PlayerPrefs。
     */
    private void SaveData()
    {
        PlayerPrefs.SetInt("HighScore", highScore);
        PlayerPrefs.SetInt("NumbersGame", numbersGame);
    }
    /**
     * @brief 重启游戏，清空地图并重置分数。
     */
    public void Restart()
    {
        //缺少删除刚落下的方块
        for(int i = 0; i < MAX_COLUMNS; i++)
        {
            for(int j = 0; j < MAX_ROWS; j++)
            {
                if (map[i, j] != null)
                {
                    Destroy(map[i, j].gameObject);
                    map[i, j] = null;
                }
            }
        }
        score = 0;
    }
    /**
     * @brief 清空所有数据，包括分数和游戏局数。
     */
    public void ClearData()
    {
        score = 0;
        highScore = 0;
        numbersGame = 0;
        SaveData();
    }
}
